#if defined(TSINGMA_MX) || defined(TSINGMA_GX) || defined(ARCTIC)
#include "sal.h"
#include "ctc_error.h"
#include "drv_api.h"
#include "sys_usw_emsg.h"
#include "sys_usw_dma.h"
#include "sys_usw_chip.h"


#define EMSG_BUF_CNT 4
#define EMSG_BUF_LEN 1024
#define EMSG_INVALID_THRD_ID 0xFFFF
#define EMSG_SYNC_TIME_OUT 1000
#define EMSG_THRD_CNT EMSG_BUF_CNT


#define EMSG_PACK_U32(BUF, VAL)\
{\
    *(uint32*)(BUF) = VAL;\
    (BUF) += sizeof(uint32);\
}

#define EMSG_PACK_U16(BUF, VAL)\
{\
    *(uint16*)(BUF) = VAL;\
    (BUF) += sizeof(uint16);\
}

#define EMSG_PACK_U8(BUF, VAL)\
{\
    *(uint8*)(BUF) = VAL;\
    (BUF) += sizeof(uint8);\
}


#define EMSG_UNPACK_U32(BUF, VAL)\
{\
    VAL = *(uint32*)(BUF);\
    (BUF) += sizeof(uint32);\
}

#define EMSG_UNPACK_U16(BUF, VAL)\
{\
    VAL = *(uint16*)(BUF);\
    (BUF) += sizeof(uint16);\
}

#define EMSG_UNPACK_U8(BUF, VAL)\
{\
    VAL = *(uint8*)(BUF);\
    (BUF) += sizeof(uint8);\
}



uint32 g_sys_emsg_seqId = 0;

typedef struct sys_emsg_master_e
{
    uint8* tx_buf[EMSG_BUF_CNT];   /*request buffer ptr*/
    uint32 tx_buf_used[CTC_B2W_SIZE(EMSG_BUF_CNT)];/* bitmap *//*Tx*/
    uint16 tx_thrd_id[EMSG_BUF_CNT]; /*reply thrd id*/

    uint8* rx_buf[EMSG_THRD_CNT]; /*reply buffer ptr*/
    uint32 reply_seqId[EMSG_THRD_CNT];/*reply seqId, 0 is invalid*/

    uint16 rx_cur_index;
    uint16 tx_cur_index;
    sal_sem_t* sync_sem[EMSG_THRD_CNT];/*reply sem ptr*/
    sys_emsg_rx_cb rx_cb[SYS_EMSG_TYPE_MAX];
    sal_spinlock_t* p_lock;
}sys_emsg_master_t;
sys_emsg_master_t* p_emsg_master[CTC_MAX_LOCAL_CHIP_NUM_PP] = {NULL};

#define SYS_EMSG_INIT_CHECK(lchip)\
    do{                                 \
        LCHIP_CHECK(lchip);         \
        SYS_LCHIP_CHECK_ACTIVE(lchip); \
        if (p_emsg_master[lchip] == NULL)    \
        { return CTC_E_NOT_INIT; } \
      }while(0)

/*Request Sync spinlock*/
#define SYS_EMSG_SLOCK(lchip)  if (p_emsg_master[lchip]->p_lock) {sal_spinlock_lock(p_emsg_master[lchip]->p_lock);}
#define SYS_EMSG_SUNLOCK(lchip)  if (p_emsg_master[lchip]->p_lock) {sal_spinlock_unlock(p_emsg_master[lchip]->p_lock);}


uint32
sys_emsg_gen_seq_id(void)
{
    if (++g_sys_emsg_seqId == 0)
    {
        g_sys_emsg_seqId++;
    }
    return g_sys_emsg_seqId;
}


sal_sem_t*
sys_emsg_sem_alloc(uint8 lchip, uint16* thrd_id, uint32 seqId)
{
    uint16 i = p_emsg_master[lchip]->rx_cur_index;
    uint16 cnt = 0;
    do
    {
        if (i >= EMSG_THRD_CNT)
        {
            i = 0;
        }
        if (p_emsg_master[lchip]->reply_seqId[i])
        {
            i++;
            continue;
        }
        if (thrd_id)
        {
            *thrd_id = i;
        }
        p_emsg_master[lchip]->rx_cur_index = i;
        p_emsg_master[lchip]->reply_seqId[i] = seqId;
        return p_emsg_master[lchip]->sync_sem[i];
    }while(++cnt < EMSG_THRD_CNT);
    return NULL;
}

sal_sem_t*
sys_emsg_sem_get(uint8 lchip, uint32 seqId, uint16* thrd_id)
{
    uint16 i = 0;
    do
    {
        if (p_emsg_master[lchip]->reply_seqId[i] != seqId)
        {
            continue;
        }
        if (thrd_id)
        {
            *thrd_id = i;
        }
        return p_emsg_master[lchip]->sync_sem[i];
    }while(++i < EMSG_THRD_CNT);
    return NULL;
}

void
sys_emsg_sem_free(uint8 lchip, uint16 thrd_id)
{
    p_emsg_master[lchip]->reply_seqId[thrd_id] = 0;
}

STATIC int32
_sys_emsg_tx_destmap(uint8 lchip, uint8 type, uint32* dest_map, uint8* direct_mode)
{
    /*direct_mode = 1, without use bridge header*/
    switch (type)
    {
        case SYS_EMSG_TYPE_SSX:
            *dest_map = MCHIP_CAP(SYS_CAP_RSV_PORT_EUNIT0_ID);
            *direct_mode = 0;
            break;
        case SYS_EMSG_TYPE_FTE:
            *dest_map = MCHIP_CAP(SYS_CAP_RSV_PORT_EUNIT0_ID) + 1;
            *direct_mode = 0;
            break;
        case SYS_EMSG_TYPE_PTP:
            *dest_map = MCHIP_CAP(SYS_CAP_RSV_PORT_EUNIT0_ID) + 2;
            *direct_mode = 0;
            break;
        case SYS_EMSG_TYPE_OAM:
            *dest_map = MCHIP_CAP(SYS_CAP_RSV_PORT_EUNIT0_ID) + 3;
            *direct_mode = 0;
            break;
        case SYS_EMSG_TYPE_LA:
            *dest_map = MCHIP_CAP(SYS_CAP_RSV_PORT_EUNIT0_ID) + 4;
            *direct_mode = 1;
            break;
        default:
            return CTC_E_INVALID_CONFIG;
    }

    return CTC_E_NONE;
}

#if (HOST_IS_LE == 1)
typedef struct {
    uint32 prio_4_3_2                        : 2;
    uint32 dest_map                          : 19;
    uint32 packet_offset                     : 8;
    uint32 bypass_ipe                        : 1;
    uint32 replicated                          : 1;
    uint32 is_int_share_fields_mode   : 1;
} ms_packet_header_word9_t;
#else
typedef struct {
    uint32 is_int_share_fields_mode      : 1;
    uint32 replicated                            : 1;
    uint32 bypass_ipe                         : 1;
    uint32 packet_offset                      : 8;
    uint32 dest_map                            : 19;
    uint32 prio_4_3_2                          : 2;
} ms_packet_header_word9_t;
#endif
STATIC int32
_sys_emsg_encode_tx_bridge_hdr(uint8 lchip, uint8* buf)
{
    /*Encode Bridge Header*/
    uint32 bheader[sizeof(ms_packet_header_tmm_t)/4] = {0};
    ms_packet_header_tmm_t* p_raw_hdr = (ms_packet_header_tmm_t*)bheader;
    uint8 priority = 15;/* highest priority */
    uint32 src_port = 0;
    uint8 src_gchip = 0;
    uint32 nh_offset = 0;

    sys_usw_get_gchip_id(lchip, &src_gchip);
    CTC_ERROR_RETURN(sys_usw_nh_get_resolved_offset(lchip, SYS_NH_RES_OFFSET_TYPE_BRIDGE_NH,  &nh_offset));
    p_raw_hdr->prio_4_1_0 = priority&0x3;
    p_raw_hdr->prio_4_3_2 = (priority>>2)&0x3;
    p_raw_hdr->bypass_ipe = 1;
    p_raw_hdr->next_hop_ptr_18_0_0 = nh_offset&0x1;
    p_raw_hdr->next_hop_ptr_18_17_1 = (nh_offset>>1)&0x1FFFF;
    p_raw_hdr->color = 3;/*CTC_QOS_COLOR_GREEN*/
    p_raw_hdr->ttl = 1;
    p_raw_hdr->from_cpu = 1;
    p_raw_hdr->mac_known = 1;
    src_port = CTC_MAP_LPORT_TO_GPORT(src_gchip, SYS_RSV_PORT_OAM_CPU_ID);
    src_port = SYS_MAP_CTC_GPORT_TO_DRV_GPORT(src_port);
    p_raw_hdr->source_port_16_0_0 = src_port&0x1;
    p_raw_hdr->source_port_16_15_1 = (src_port>>1)&0x7FFF;

#if (SDK_WORK_PLATFORM == 0)
        CTC_ERROR_RETURN(sys_usw_dword_reverse_copy((uint32*)buf, bheader, sizeof(ms_packet_header_tmm_t)/4));
        CTC_ERROR_RETURN(sys_usw_swap32((uint32*)buf, sizeof(ms_packet_header_tmm_t) / 4, FALSE))
#else
        CTC_ERROR_RETURN(sys_usw_byte_reverse_copy(buf, (uint8*)(&bheader[0]), sizeof(ms_packet_header_tmm_t)));
#endif

    return CTC_E_NONE;
}


int32
sys_emsg_tx(uint8 lchip, uint16 len, uint8* buf)
{
    int32 ret = CTC_E_NONE;
    sys_emsg_hdr_t* p_hdr = (sys_emsg_hdr_t*)buf;
    ctc_pkt_tx_t* pkt_tx = NULL;
    uint32 dest_map = 0;
    uint16 i = 0;
    uint8 direct_mode = 0;

    MALLOC_ZERO(MEM_SYSTEM_MODULE, pkt_tx, sizeof(ctc_pkt_tx_t));

    if(NULL == pkt_tx)
    {
        return CTC_E_NO_MEMORY;
    }

    CTC_ERROR_GOTO(_sys_emsg_tx_destmap(lchip, p_hdr->type, &dest_map, &direct_mode), ret, error_out);
    pkt_tx->mode = CTC_PKT_MODE_DMA;
    pkt_tx->lchip = lchip;
    pkt_tx->tx_info.priority = 15;
    pkt_tx->skb.data = buf;

    if (direct_mode)
    {
        pkt_tx->skb.len = len << 2;
        pkt_tx->skb.head = buf;
    }
    else
    {
        ms_packet_header_word9_t* p_raw_hdr = (ms_packet_header_word9_t*)(buf - SYS_USW_PKT_HEADER_LEN);
        p_raw_hdr->dest_map = dest_map;
#if (SDK_WORK_PLATFORM == 0)
        *(uint32*)p_raw_hdr = sal_htonl(*(uint32*)p_raw_hdr);
#endif
        pkt_tx->skb.len = len << 2;
        pkt_tx->skb.head = buf - SYS_USW_PKT_HEADER_LEN;
    }

    /* endian convert */
    for (i = 0; i < p_hdr->len; i++)
    {
        ((uint32*)buf)[i] = sal_htonl(((uint32*)buf)[i]);
    }
    CTC_ERROR_GOTO(sys_usw_dma_pkt_tx(lchip, pkt_tx), ret, error_out);

error_out:
    if(pkt_tx)
    {
        mem_free(pkt_tx);
    }

    return ret;
}

int32
sys_emsg_rx(ctc_pkt_rx_t* p_rx)
{
    uint8 lchip = p_rx->lchip;
    sys_emsg_hdr_t* p_hdr= (sys_emsg_hdr_t*)(p_rx->pkt_buf[0].data + p_rx->pkt_hdr_len);
    int32 ret = CTC_E_NONE;

    if (!p_hdr->ack)
    {
        /*requset*/
        if (p_hdr->type < SYS_EMSG_TYPE_MAX && p_emsg_master[lchip]->rx_cb[p_hdr->type])
        {
            p_emsg_master[lchip]->rx_cb[p_hdr->type](lchip, (uint8*)p_hdr);
        }
        else if (p_hdr->sync)
        {
            /*reply SYS_EMSG_E_NOT_HANDLED*/
            uint16 buf_id = 0;
            uint8* buf = NULL;
            uint32 seqId = p_hdr->seqId;
            uint8* ptr;

            ret = sys_emsg_buf_alloc(lchip, p_hdr->type, 1, 0, &buf_id, &buf);
            if (ret == CTC_E_NO_RESOURCE)
            {
                /*Should Try Again*/
               return ret;
            }
            p_hdr = (sys_emsg_hdr_t*)buf;
            p_hdr->seqId = seqId;
            ptr = buf + EMSG_HDR_LEN;
            EMSG_PACK_U32(ptr, SYS_EMSG_E_NOT_HANDLED);
            p_hdr->len = EMSG_HDR_LEN + sizeof(uint32);
            p_hdr->len >>= 2;/*4B*/
            ret = sys_emsg_reply(lchip, buf, p_hdr->len);
            if (ret < 0)
            {
                /*Debug Error*/
                sys_emsg_buf_free(lchip, buf_id);
                return ret;
            }
            sys_emsg_buf_free(lchip, buf_id);
        }
    }
    else
    {
        /*reply*/
        uint16 thrd_id = 0;
        sal_sem_t* p_sem;

        p_sem = sys_emsg_sem_get(lchip, p_hdr->seqId, &thrd_id);
        if (p_sem)
        {
            SYS_EMSG_SLOCK(lchip);
            sal_memcpy(p_emsg_master[lchip]->rx_buf[thrd_id], (uint8*)p_hdr, p_hdr->len * 4);
            SYS_EMSG_SUNLOCK(lchip);
            sal_sem_give(p_sem);
        }
    }
    return CTC_E_NONE;
}

STATIC int32
_sys_emsg_error_code_map(uint32 status)
{
    switch(status)
    {
        case SYS_EMSG_E_NOT_HANDLED:
            return CTC_E_NOT_SUPPORT;
        default:
            break;
    }
    return CTC_E_NONE;
}
#define ______API______

int32
sys_emsg_buf_alloc(uint8 lchip, uint8 type, uint8 ack, uint8 sync, uint16* buf_id, uint8** buf)
{
    uint16 i = 0;
    uint16 cnt = 0;
    sys_emsg_hdr_t* ptr;

    if (NULL == p_emsg_master[lchip])
    {
        return CTC_E_NOT_INIT;
    }
    CTC_PTR_VALID_CHECK(buf);

    i = p_emsg_master[lchip]->tx_cur_index;
    do
    {
        if (i >= EMSG_BUF_CNT)
        {
            i = 0;
        }
        if (p_emsg_master[lchip]->tx_buf_used[i >> 5] & (1 << (i & 0x1F)))
        {
            i++;
            continue;
        }
        p_emsg_master[lchip]->tx_thrd_id[i] = EMSG_INVALID_THRD_ID;
        p_emsg_master[lchip]->tx_buf_used[i >> 5] |= (1 << (i & 0x1F));
        if (buf_id)
        {
            *buf_id = i;
        }
        ptr = (sys_emsg_hdr_t*)(p_emsg_master[lchip]->tx_buf[i]+ SYS_USW_PKT_HEADER_LEN);
        ptr->type = type;
        ptr->sync = ack ? 0 : sync;
        ptr->ack  = ack;
        ptr->seqId = i;/* buf_id */
        *buf = (uint8*)ptr;
        p_emsg_master[lchip]->tx_cur_index = i;
        return CTC_E_NONE;
    }while (++cnt < EMSG_BUF_CNT);

    return CTC_E_NO_RESOURCE;
}

int32
sys_emsg_buf_free(uint8 lchip, uint16 buf_id)
{
    if (NULL == p_emsg_master[lchip])
    {
        return CTC_E_NOT_INIT;
    }
    /*UNSET*/
    p_emsg_master[lchip]->tx_buf_used[buf_id >> 5] &= (~(1 << (buf_id & 0x1F)));
    if (p_emsg_master[lchip]->tx_thrd_id[buf_id] != EMSG_INVALID_THRD_ID)
    {
        sys_emsg_sem_free(lchip, p_emsg_master[lchip]->tx_thrd_id[buf_id]);
        p_emsg_master[lchip]->tx_thrd_id[buf_id] = EMSG_INVALID_THRD_ID;
    }
    return CTC_E_NONE;
}

int32
sys_emsg_request(uint8 lchip, uint8* buf, uint16 len, uint8** r_buf)
{
    int32 ret = CTC_E_NONE;
    uint16 thrd_id = 0;
    sal_sem_t* p_sem = NULL;
    uint32 status = 0;
    uint8* ptr;
    sys_emsg_hdr_t* p_hdr = (sys_emsg_hdr_t*)buf;

    if (NULL == p_emsg_master[lchip])
    {
        return CTC_E_NOT_INIT;
    }
    CTC_PTR_VALID_CHECK(buf);


    if (p_hdr->sync)
    {
        uint16 buf_id = p_hdr->seqId;
        SYS_EMSG_SLOCK(lchip);
        p_hdr->seqId = sys_emsg_gen_seq_id();
        p_sem = sys_emsg_sem_alloc(lchip, &thrd_id, p_hdr->seqId);
        SYS_EMSG_SUNLOCK(lchip);
        if (NULL == p_sem)
        {
            return CTC_E_NO_RESOURCE;
        }
        p_emsg_master[lchip]->tx_thrd_id[buf_id] = thrd_id;
    }
    else
    {
        p_hdr->seqId = 0;
    }

    ret = sys_emsg_tx(lchip, len, buf);
    if (!p_hdr->sync || ret < 0)
    {
        return ret;
    }

    /*stake sem, wait time out 1s*/
    ret = sal_sem_take(p_sem, EMSG_SYNC_TIME_OUT);
    if (ret < 0)
    {
        sys_emsg_sem_free(lchip, thrd_id);
        return CTC_E_HW_TIME_OUT;
    }

    *r_buf = p_emsg_master[lchip]->rx_buf[thrd_id];

    //*r_buf += EMSG_HDR_LEN;
    ptr = *r_buf + EMSG_HDR_LEN;
    EMSG_UNPACK_U32(ptr, status);

    return _sys_emsg_error_code_map(status);
}

int32
sys_emsg_reply(uint8 lchip, uint8* buf, uint16 len)
{
    if (NULL == p_emsg_master[lchip])
    {
        return CTC_E_NOT_INIT;
    }

    CTC_PTR_VALID_CHECK(buf);
    return sys_emsg_tx(lchip, len, buf);
}


int32
sys_emsg_rx_register(uint8 lchip, sys_emsg_type_t type, sys_emsg_rx_cb cb)
{
    SYS_EMSG_INIT_CHECK(lchip);
    CTC_MAX_VALUE_CHECK(type, SYS_EMSG_TYPE_MAX - 1);
    p_emsg_master[lchip]->rx_cb[type] = cb;
    return CTC_E_NONE;
}

int32
sys_emsg_deinit(uint8 lchip)
{
    uint16 i =0;
    LCHIP_CHECK(lchip);
    if (NULL == p_emsg_master[lchip])
    {
        return CTC_E_NONE;
    }

    for (i = 0; i < EMSG_BUF_CNT; i++)
    {
        mem_free(p_emsg_master[lchip]->tx_buf[i]);
    }
    for (i = 0; i < EMSG_THRD_CNT; i++)
    {
        if (p_emsg_master[lchip]->sync_sem[i])
        {
            sal_sem_give(p_emsg_master[lchip]->sync_sem[i]);
            sal_sem_destroy(p_emsg_master[lchip]->sync_sem[i]);
        }
        mem_free(p_emsg_master[lchip]->rx_buf[i]);
    }
    if (p_emsg_master[lchip]->p_lock)
    {
        sal_spinlock_destroy(p_emsg_master[lchip]->p_lock);
    }
    mem_free(p_emsg_master[lchip]);
    return CTC_E_NONE;
}


#if 0
/*test start*/
// test code
sal_task_t* p_emsg_task_hcpu;

void
sys_emsg_thread_hcpu_task_test(void* param)
{
    int32 ret = 0;
    uint16 i = 0;
    uint16 j = 0;
    uint8* ptr;
    sys_emsg_hdr_t* p_hdr;
    ctc_pkt_rx_t pkt_rx;
    ctc_pkt_buf_t pkt_buf;
    uint8 lchip = *((uint8*)param);

    while (1)
    {
        ret = sal_sem_take(p_emsg_sem_hcpu, SAL_SEM_FOREVER);
        if (0 != ret)
        {
            continue;
        }
        for (i = 0; i < EMSG_THRD_CNT; i++)
        {
            if (!g_rx_buf_test_valid_hcpu[i])
            {
                continue;
            }
            ptr = g_rx_buf_test_hcpu[i];
            p_hdr = (sys_emsg_hdr_t*)ptr;
            sal_printf("HCPU Receive:\n");
            for (j = 0; j < p_hdr->len; j++)
            {
                sal_printf("0x%.4x:    0x%.8x\n", j*4, ((uint32*)ptr)[j]);
            }
            sal_memset(&pkt_rx, 0, sizeof(pkt_rx));
            pkt_rx.pkt_buf = &pkt_buf;
            pkt_buf.data = ptr;
            pkt_buf.len = p_hdr->len;
            pkt_rx.pkt_len = p_hdr->len * 4;
            pkt_rx.pkt_hdr_len = SYS_USW_PKT_HEADER_LEN;
            ret = sys_emsg_rx(&pkt_rx);
            if (ret < 0)
            {
                sal_printf("sys_emsg_rx error! ret = %d\n", ret);
            }
            g_rx_buf_test_valid_hcpu[i] = 0;
        }
    }
}

int32
sys_emsg_send_test()
{
    uint8 lchip = 0;
    uint16 buf_id = 0;
    uint8* buf = NULL;
    int32 ret = 0;
    sys_emsg_hdr_t* p_hdr;
    uint8* r_buf;
    uint8* ptr ;

    ret = sys_emsg_buf_alloc(lchip, SYS_EMSG_TYPE_READ_ADDR, 0, 1, &buf_id, &buf);
    if (ret == CTC_E_NO_RESOURCE)
    {
        /*Should Try Again*/
       return ret;
    }
    p_hdr = (sys_emsg_hdr_t*)buf;
    ptr = buf + EMSG_HDR_LEN;
    EMSG_PACK_U32(ptr, 0x12345678);
    p_hdr->len = EMSG_HDR_LEN + sizeof(uint32);
    p_hdr->len >>= 2;
    ret = sys_emsg_request(lchip, buf, p_hdr->len, &r_buf);
    if (ret < 0)
    {
        /*Debug Error*/
        sys_emsg_buf_free(lchip, buf_id);
        return ret;
    }
    if (r_buf)
    {
        uint16 j = 0;
        p_hdr = (sys_emsg_hdr_t*)r_buf;
        sal_printf("ECPU Reply:\n");
        for (j = 0; j < p_hdr->len; j++)
        {
            sal_printf("0x%.4x:    0x%.8x\n", j * 4, ((uint32*)r_buf)[j]);
        }
    }
    sys_emsg_buf_free(lchip, buf_id);
    return CTC_E_NONE;
}
/*test end*/

#endif

/*EMSG do not need support warmboot*/
int32
sys_emsg_init(uint8 lchip)
{
    int32 ret = CTC_E_NONE;
    uint16 i = 0;

    if (p_emsg_master[lchip])
    {
        return CTC_E_NONE;
    }
    p_emsg_master[lchip] = mem_malloc(MEM_SYSTEM_MODULE, sizeof(sys_emsg_master_t));
    if (NULL == p_emsg_master[lchip])
    {
        return CTC_E_NO_MEMORY;
    }
    sal_memset(p_emsg_master[lchip], 0, sizeof(sys_emsg_master_t));

    for (i = 0; i < EMSG_BUF_CNT; i++)
    {
        p_emsg_master[lchip]->tx_buf[i] = mem_malloc(MEM_SYSTEM_MODULE, EMSG_BUF_LEN);
        if (NULL == p_emsg_master[lchip]->tx_buf[i])
        {
            ret = CTC_E_NO_MEMORY;
            goto error_back;
        }
        sal_memset(p_emsg_master[lchip]->tx_buf[i], 0, EMSG_BUF_LEN);
        p_emsg_master[lchip]->tx_thrd_id[i] = EMSG_INVALID_THRD_ID;
        _sys_emsg_encode_tx_bridge_hdr(lchip, p_emsg_master[lchip]->tx_buf[i]);
    }
    for (i = 0; i < EMSG_THRD_CNT; i++)
    {
        ret = sal_sem_create(&p_emsg_master[lchip]->sync_sem[i], 0);
        if (ret < 0)
        {
            goto error_back;
        }
        p_emsg_master[lchip]->rx_buf[i] = mem_malloc(MEM_SYSTEM_MODULE, EMSG_BUF_LEN);
        if (NULL == p_emsg_master[lchip]->rx_buf[i])
        {
            ret = CTC_E_NO_MEMORY;
            goto error_back;
        }
        sal_memset(p_emsg_master[lchip]->rx_buf[i], 0, EMSG_BUF_LEN);
    }
    ret = sal_spinlock_create(&p_emsg_master[lchip]->p_lock);
    if (ret || !p_emsg_master[lchip]->p_lock)
    {
        ret = CTC_E_NO_RESOURCE;
        goto error_back;
    }

    return CTC_E_NONE;
error_back:
    sys_emsg_deinit(lchip);
    return ret;
}
#endif

